/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.jeff.springWebTestNG.concurrent;

import java.util.concurrent.CountDownLatch;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * This class emulates the 'gate' policy using Latch, which allows multiple threads released
 * once a latch release event arrives
 * 
 * @author zhou.zhefu
 */
public class LatchEmulator {
    private static final int N_FLOOD = 5;
    private final CountDownLatch startGate = new CountDownLatch(1);
    private final CountDownLatch endGate = new CountDownLatch(N_FLOOD);
    
    public void start() {
        try {
            //init all the thread before startGate flush
            for (int i = 1; i <= N_FLOOD; i++) {
                new Thread(new Flood(i)).start();
            }
            long startTime = System.nanoTime();
            startGate.countDown();
            endGate.await();
            long endTime = System.nanoTime();
            
            System.out.println("All Floods flushed within " + (endTime - startTime) + " nano seconds. ");
        } catch (InterruptedException ex) {
            Logger.getLogger(LatchEmulator.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    private class Flood implements Runnable {
        int id;

        public Flood(int id) {
            this.id = id;
        }
        
        @Override
        public void run() {
            try {
                startGate.await();
                System.out.println(this + " arrived.");
//                Thread.sleep(1);
                endGate.countDown();
            } catch (InterruptedException ex) {
                Logger.getLogger(Flood.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        @Override
        public String toString() {
            return "Flood[" + id + "]";
        }
    }
}
